/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import 'dart:async';
import 'dart:convert';

import 'package:flutter/services.dart';

import 'folder_options.dart';

///折叠屏插件通信类
class FolderStackPlugin {
  static const EventChannel _folderStatusEventChannel =
      EventChannel('avoid_area/folder_state');
  static Stream<FoldingFeature>? _folderStatusEvents;

  ///折叠屏信息变换监听
  static Stream<FoldingFeature> get folderStateEvents {
    try {
      _folderStatusEvents ??= _repeatLatest(
        _folderStatusEventChannel
            .receiveBroadcastStream()
            .map((event) => FoldingFeature.fromJson(jsonDecode(event))),
      );
      return _folderStatusEvents!;
    } catch (e) {
      return const Stream.empty();
    }
  }

  static Stream<T> _repeatLatest<T>(Stream<T> original) {
    var done = false;
    T? latest;
    var currentListeners = <MultiStreamController<T>>{};
    original.listen((event) {
      latest = event;
      for (var listener in [...currentListeners]) {
        listener.addSync(event);
      }
    }, onError: (Object error, StackTrace stack) {
      for (var listener in [...currentListeners]) {
        listener.addErrorSync(error, stack);
      }
    }, onDone: () {
      done = true;
      latest = null;
      for (var listener in currentListeners) {
        listener.closeSync();
      }
      currentListeners.clear();
    });
    return Stream.multi((controller) {
      if (done) {
        controller.close();
        return;
      }
      currentListeners.add(controller);
      var latestValue = latest;
      if (latestValue != null) controller.add(latestValue);
      controller.onCancel = () {
        if (!done) {
          currentListeners.remove(controller);
        }
      };
    });
  }
}
